package com.jee.ssm.modules.guideScreen.controller;

import com.jee.ssm.model.GuideScreen;
import com.jee.ssm.modules.guideScreen.services.GuideScreenService;
import com.jee.ssm.common.log.AdminControllerLog;
import com.jee.ssm.common.socket.guideScreen.SocketHandle;
import com.jee.ssm.common.socket.guideScreen.SocketServer;
import com.jee.ssm.modules.guideScreen.timer.RefreshData;
import com.jee.ssm.modules.ssm.controller.AdminBaseController;
import com.jee.ssm.model.json.Tip;
import com.jee.ssm.model.param.ParamMap;
import com.jee.ssm.common.utils.ImageWordUtils;
import com.jee.ssm.common.utils.UUIDFactory;
import com.jee.ssm.common.utils.hik.HikUtils;

import org.apache.log4j.Logger;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
* 诱导屏管理 Controller
* @author GaoXiang
* @version 1.0
*/
@Controller
@RequestMapping("/guideScreen")
public class GuideScreenController extends AdminBaseController<GuideScreen> {

	private Logger logger = Logger.getLogger(GuideScreenController.class);

	/**
     * 进入诱导屏添加页面 携带一个生成的id --> longId
     * @param model 返回的实体容器
     * @return 添加页面
     */
    @RequestMapping(value="/add")
    @RequiresPermissions("guideScreen:add")
    public String add(ModelMap model){

        model.put("longId", UUIDFactory.getStringId());
        return "manager/guideScreen/add";
    }


    /**
     * 进入诱导屏编辑页面
     * @param model 返回诱导屏的容器
     * @param id 诱导屏id
     * @return 编辑页面
     */
    @RequestMapping(value="/edit")
    @RequiresPermissions("guideScreen:edit")
    public String edit(ModelMap model, @RequestParam String id) {

        model.put("data",guideScreenService.selectById(id));
        return "manager/guideScreen/edit";
    }


    /**
     * 诱导屏添加
     * @param guideScreen 带id的诱导屏对象
     * @return 成功状态
     */
    @RequestMapping(value="/save")
    @ResponseBody
    @RequiresPermissions("guideScreen:add")
    @AdminControllerLog(description = "添加诱导屏" )
    public Tip save(GuideScreen guideScreen)  {

        try {
            guideScreenService.insert(guideScreen);
            return new Tip();
        } catch (Exception e) {
            //e.printStackTrace();
            return new Tip(1,"添加失败！");
        }

    }


    /**
     * 根据 id 修改诱导屏
     * @param guideScreen 带id的诱导屏对象
     * @return 成功状态
     */
    @RequestMapping(value="/update")
    @ResponseBody
    @RequiresPermissions("guideScreen:edit")
    @AdminControllerLog(description = "修改诱导屏")
    public Tip update(GuideScreen guideScreen, HttpServletRequest request) {
        try {
        	guideScreen.setUpdateTime(new Date());
            guideScreenService.updateById(guideScreen);
            return new Tip();
        } catch (Exception e) {
            e.printStackTrace();
            return new Tip(1,"修改失败！");
        }
    }
    
    @RequestMapping(value="/editAndSend")
    @ResponseBody
    @RequiresPermissions("guideScreen:edit")
    public Tip editAndSend(GuideScreen guideScreen, HttpServletRequest request) {
    	Tip tip = new Tip();
    	try {
    		guideScreen.setStatus(1);
        	guideScreen.setUpdateTime(new Date());
    		SocketHandle s = SocketServer.socketMap.get(guideScreen.getNumber());
    		if(s != null) {
    			String num = "001";
        		String imageName = guideScreen.getNumber() + "_" + guideScreen.getBaiduNumber() + "_" + num + ".jpg";
        		
            	String url = "/images/guide-screen/" + guideScreen.getName() + "_" + guideScreen.getNumber() + "/" + System.currentTimeMillis() + "/";
            	String filePath = request.getServletContext().getRealPath(url);
            	File d = new File(filePath);
            	if(!d.exists() && !d.isDirectory()) {
    				d.mkdirs();
    			}
            	String fileName = "play" + num + ".lst";
            	File file = new File(filePath + fileName);
            	if(file.exists()){
            		file.delete();
            	}
            	file.createNewFile();
                //创建文件成功后，写入内容到文件里
                writeFileContent(filePath + fileName, "[all]\nitems=1\n[item1]\nparam=5000,255,255,1,0,1,1,0,1\nimg1=0,0," + imageName + ",0,192,160\nimgparam1=5000");

                Tip topLeft = HikUtils.getLeftPlot(guideScreen.getParkTopNumber());
                String top = "0";
                if(topLeft.getSuccess()) {
                	top = topLeft.getMessage();
                }
                Tip bottomLeft = HikUtils.getLeftPlot(guideScreen.getParkBottomNumber());
                String bottom = "0";
                if(bottomLeft.getSuccess()) {
                	bottom = bottomLeft.getMessage();
                }
                
            	getImage(request, filePath, imageName, guideScreen.getBaiduNumber(), guideScreen.getTopWord() + top, guideScreen.getBottomWord() + bottom);
            	
            	guideScreen.setPlayNumber(1);
            	guideScreen.setPlayFileUrl(url);
            	guideScreen.setPlayFileName(fileName);
            	guideScreen.setImageName(imageName);
            	
            	guideScreenService.updateById(guideScreen);
            	
                sendToScreen(guideScreen.getNumber(), guideScreen.getPlayNumber(), filePath, fileName, imageName, true);
    		} else {
    			guideScreenService.updateById(guideScreen);
    		}

        } catch (Exception e) {
            e.printStackTrace();
            tip = new Tip(1,"修改失败！");
        }
    	
    	return tip;
    }
    
    @RequestMapping(value = "/clean")
    @ResponseBody
    @RequiresPermissions("guideScreen:clean")
    public Tip clean(String number) {
    	Tip tip = new Tip();
    	SocketHandle s = SocketServer.socketMap.get(number);
		 if(s != null) {
			 try {
				 guideScreenService.clean(number);
			 } catch (Exception e) {
				 e.printStackTrace();
				 logger.info("清除数据库失败");
			 }
			 s.cleanAll();
		 } else {
			 tip = new Tip(1, "设备不在线");
		 }
    	return tip;
    }
    
	public void getImage(HttpServletRequest request, String path, String name, String number, String top, String bottom) throws FileNotFoundException, IOException {
		String fileName = number + ".jpg";
		File file = new File(path);
		if(!file.exists() && !file.isDirectory()) {
			file.mkdirs();
		}
		saveToFile("http://jiaotong.baidu.com/guidingscreen/screen/image?id=" + number, path + fileName);
		File f = new File(path + fileName);
		BufferedImage img = ImageIO.read(new FileInputStream(f));
		int width = img.getWidth();
		int height1 = img.getHeight();
		
		BufferedImage wordImg1 = ImageWordUtils.getPictureByWord(top, width);
		BufferedImage wordImg2 = ImageWordUtils.getPictureByWord(bottom, width);
		int height2 = wordImg1.getHeight();
		int height3 = wordImg2.getHeight();
		 
		BufferedImage tag = new BufferedImage(width, height1 + height2 + height3, BufferedImage.TYPE_INT_RGB);
		 
		Graphics g = tag.createGraphics();
		g.drawImage(wordImg1, 0, 0, width, height2, null);
		g.drawImage(img, 0, height2, width, height1, null);
		g.drawImage(wordImg2, 0, height1 + height2, width , height3, null);
		 
		String result = path + name;
		ImageIO.write(tag, "JPEG", new File(result));
	}
    
	public static void saveToFile(String destUrl, String path) {
		FileOutputStream fos = null;
		BufferedInputStream bis = null;
		HttpURLConnection httpUrl = null;
		URL url = null;
		int BUFFER_SIZE = 1024;
		byte[] buf = new byte[BUFFER_SIZE];
		int size = 0;
		try {
			url = new URL(destUrl);
			httpUrl = (HttpURLConnection) url.openConnection();
			httpUrl.connect();
			bis = new BufferedInputStream(httpUrl.getInputStream());
			fos = new FileOutputStream(path);
			while ((size = bis.read(buf)) != -1) {
				fos.write(buf, 0, size);
			}
			fos.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassCastException e) {
			e.printStackTrace();
		} finally {
			try {
				fos.close();
				bis.close();
				httpUrl.disconnect();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (NullPointerException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
     * 向文件中写入内容
     * @param filepath 文件路径与名称
     * @param newstr  写入的内容
     * @return
     * @throws IOException
     */
	public static boolean writeFileContent(String filepath,String newstr) throws IOException {
		Boolean bool = false;
        String filein = newstr+"\r\n";//新写入的行，换行
        String temp  = "";
        
        FileInputStream fis = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        FileOutputStream fos  = null;
        PrintWriter pw = null;
        try {
            File file = new File(filepath);//文件路径(包括文件名称)
            //将文件读入输入流
            fis = new FileInputStream(file);
            isr = new InputStreamReader(fis);
            br = new BufferedReader(isr);
            StringBuffer buffer = new StringBuffer();
            
            //文件原有内容
            while((temp =br.readLine())!=null){
                buffer.append(temp);
                // 行与行之间的分隔符 相当于“\n”
                buffer = buffer.append(System.getProperty("line.separator"));
            }
            buffer.append(filein);
            
            fos = new FileOutputStream(file);
            pw = new PrintWriter(fos);
            pw.write(buffer.toString().toCharArray());
            pw.flush();
            bool = true;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //不要忘记关闭
            if (pw != null) {
                pw.close();
            }
            if (fos != null) {
                fos.close();
            }
            if (br != null) {
                br.close();
            }
            if (isr != null) {
                isr.close();
            }
            if (fis != null) {
                fis.close();
            }
        }
        return bool;
    }
    
    @RequestMapping(value="/relate")
    @RequiresPermissions("guideScreen:edit")
    public String relate(ModelMap model, String id) {
    	model.put("data", guideScreenService.selectById(id));
        return "manager/guideScreen/relate";
    }


    /**
     * 根据 id 删除诱导屏
     * @param id 诱导屏id
     * @return 成功状态
     */
    @RequestMapping(value="/delete")
    @ResponseBody
    @RequiresPermissions("guideScreen:delete")
    @AdminControllerLog(description = "删除诱导屏" )
    public Tip delete(@RequestParam String id) {

        try {
            guideScreenService.deleteById(id);
            return new Tip();
        } catch (Exception e) {
            //e.printStackTrace();
            return new Tip(1,"删除失败！");
        }

    }


    /**
     * 根据 id 列表批量删除
     * @param ids 诱导屏id List
     * @return 成功状态
     */
    @RequestMapping(value="/deleteByIds")
    @ResponseBody
    @RequiresPermissions("guideScreen:delete")
    @AdminControllerLog(description = "批量删除诱导屏" )
    public Tip deleteByIds(@RequestParam("ids") List<String> ids) {

        try {
            guideScreenService.deleteByIds(ids);
            return new Tip();
        } catch (Exception e) {
            //e.printStackTrace();
            return new Tip(1,"批量删除失败！");
        }

    }


    /**
     * 根据 id 查找诱导屏
     * @param id 诱导屏id
     * @return 诱导屏对象 json
     */
    @RequestMapping(value="/findJson")
    @ResponseBody
    @RequiresPermissions("guideScreen:list")
    public GuideScreen find(@RequestParam String id) {

        return guideScreenService.selectById(id);
    }


    /**
     * 获取诱导屏列表 获取全部 不分页
     * @param request 请求参数
     * @return 诱导屏列表页面
     */
    @RequestMapping(value="/all")
    @RequiresPermissions("guideScreen:list")
    public String all(HttpServletRequest request,ModelMap modelMap) {

        return list(request,modelMap,1,0);
    }


    /**
     * 获取诱导屏列表 分页
     * @param request 请求参数
     * @param page 第几页
     * @param size 每页大小
     * @return 诱导屏列表页面
     */
    @RequestMapping(value="/list")
    @RequiresPermissions("guideScreen:list")
    public String list(HttpServletRequest request,ModelMap modelMap,Integer page,Integer size) {

        modelMap.put("pageInfo",guideScreenService.list(new ParamMap(request),page,size));
        modelMap.putAll(new ParamMap(request));
        return "manager/guideScreen/list";
    }
    
    @RequestMapping(value="/send")
    @RequiresPermissions("guideScreen:send")
    @ResponseBody
    public Tip send(String id, HttpServletRequest request) {
    	Tip tip = new Tip();
    	GuideScreen gs = guideScreenService.selectById(id);
    	if(gs != null) {
    		try {
    			Integer number = gs.getPlayNumber();
//    			System.out.println("当前执行第" + number + "个图片");
    			boolean clean = false;
    			if(number == null) {
    				clean = true;
    				gs.setPlayNumber(1);
//    				gs.setPlayFileUrl("/images/guide-screen/" + gs.getName() + "_" + gs.getNumber() + "/" + System.currentTimeMillis() + "/");
					gs.setPlayFileUrl("/images/guide-screen/download-method/" + gs.getName() + "_" + gs.getNumber() + "/" + System.currentTimeMillis() + "/");
    			} else if(number <50) {
    				gs.setPlayNumber(number + 1);
    			} else {
    				clean = true;
    				gs.setPlayNumber(1);
    				gs.setPlayFileUrl("/images/guide-screen/" + gs.getName() + "_" + gs.getNumber() + "/" + System.currentTimeMillis() + "/");
    			}
    			String num = createNumberByPlayNumber(gs.getPlayNumber());
    			String imageName = gs.getNumber() + "_" + gs.getBaiduNumber() + "_" + num + ".jpg";
    			String url = gs.getPlayFileUrl();
            	String filePath = request.getServletContext().getRealPath(url);
            	File d = new File(filePath);
            	if(!d.exists() && !d.isDirectory()) {
    				d.mkdirs();
    			}
            	String fileName = "play" + num + ".lst";
            	File file = new File(filePath + fileName);
            	if(file.exists()){
            		file.delete();
            	}
            	file.createNewFile();
                //创建文件成功后，写入内容到文件里
                writeFileContent(filePath + fileName, "[all]\nitems=1\n[item1]\nparam=5000,255,255,1,0,1,1,0,1\nimg1=0,0," + imageName + ",0,192,160\nimgparam1=5000");

                Tip topLeft = HikUtils.getLeftPlot(gs.getParkTopNumber());
                String top = "0";
                if(topLeft.getSuccess()) {
                	top = topLeft.getMessage();
                }
                Tip bottomLeft = HikUtils.getLeftPlot(gs.getParkBottomNumber());
                String bottom = "0";
                if(bottomLeft.getSuccess()) {
                	bottom = bottomLeft.getMessage();
                }

            	getImage(request, filePath, imageName, gs.getBaiduNumber(), gs.getTopWord() + top, gs.getBottomWord() + bottom);
            	gs.setUpdateTime(new Date());
            	gs.setPlayFileUrl(url);
            	gs.setPlayFileName(fileName);
            	gs.setImageName(imageName);

                guideScreenService.updateById(gs);

                sendToScreen(gs.getNumber(), gs.getPlayNumber(), filePath, fileName, imageName, clean);
    		} catch (Exception e) {
    			e.printStackTrace();
    			tip = new Tip(1, "发送文件生成异常或修改数据异常");
    		}
    	} else {
    		tip = new Tip(2, "未找到该数据");
    	}
    	return tip;
    }

	@RequestMapping(value="/send2")
	@ResponseBody
	public Tip send2(String id, HttpServletRequest request) {
    	GuideScreen gs = guideScreenService.selectById(id);
		boolean clean;
		String url = "/images/guide-screen/download-method/", fileName, imageName;
		WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
		ServletContext servletContext = webApplicationContext.getServletContext();
		String filePath = servletContext.getRealPath(url);
		//当前已经是第一张图片
		clean = true;
		gs.setPlayNumber(1);
		fileName = "play001.lst";
		imageName = "cxz.jpg";
		gs.setUpdateTime(new Date());
		gs.setPlayFileUrl(url);
		gs.setPlayFileName(fileName);
		gs.setImageName(imageName);
		try {
			guideScreenService.updateById(gs);
		} catch (Exception e) {
			e.printStackTrace();
			logger.info("修改类型失败");
		}
		sendToScreen2(gs.getPlayNumber(), gs.getNumber(), filePath, fileName, imageName, clean);
		return new Tip();
	}


    
    private String createNumberByPlayNumber(Integer playNumber) {
		String number = "";
		if(playNumber > 0 && playNumber < 10) {
			number = "00" + playNumber;
		} else if(playNumber > 9 && playNumber < 100 ) {
			number = "0" + playNumber;
		} else {
			number = String.valueOf(playNumber);
		}
		return number;
	}
    
    public Tip sendToScreen(String number, Integer n, String url, String fileName, String imageName, boolean clean) {
    	Tip tip = new Tip();
		 SocketHandle s = SocketServer.socketMap.get(number);
		 if(s != null) {
			 s.cleanAll();
			 try {
//				 Thread.sleep(1000);
				 List<Byte> list = getFileInfo(url + imageName);
				 s.sendFileName(list.size(), imageName);
				 s.sendFile(list);
				 
//				 Thread.sleep(1000);
				 List<Byte> playlist = getFileInfo(url + fileName);
				 s.sendFileName(playlist.size() + 100, fileName);
				 s.sendFile(playlist);
				 
//				 Thread.sleep(1000);
			} catch (IOException e) {
				e.printStackTrace();
//			} catch (InterruptedException e) {
//				e.printStackTrace();
			}
			 s.play(n);
		 } else {
			 tip = new Tip(1, "设备不在线");
		 }

		 return tip;
	 }
    
    public List<Byte> getFileInfo(String url) throws IOException {
		 
		 List<Byte> bytes = new ArrayList<>();
		 byte[] f = InputStream2ByteArray(url);
		 for(byte y : f) {
			 if(y == 170 || y == -86) {
				 bytes.add((byte)0xEE);
				 bytes.add((byte)0x0A);
			 } else if(y == 204 || y == -52) {
				 bytes.add((byte)0xEE);
				 bytes.add((byte)0x0C);
			 } else if(y == 238 || y == -18) {
				 bytes.add((byte)0xEE);
				 bytes.add((byte)0x0E);
			 } else {
				 bytes.add(y);
			 }
		 }
		 return bytes;
	}
    
    private byte[] InputStream2ByteArray(String filePath) throws IOException {
		InputStream in = new FileInputStream(filePath);
		byte[] data = toByteArray(in);
		in.close();
		return data;
	}
		 
	private byte[] toByteArray(InputStream in) throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024 * 4];
		int n = 0;
		while ((n = in.read(buffer)) != -1) {
			out.write(buffer, 0, n);
		}
		return out.toByteArray();
	}


	private void sendToScreen2(Integer n, String number, String url, String fileName, String imageName, boolean clean) {

		SocketHandle s = SocketServer.socketMap.get(number);
		if(s != null) {
			if(clean) {
				s.cleanAll();
			}
			try {
				List<Byte> list = getFileInfo(url + imageName);
				s.sendFileName(list.size(), imageName);
				s.sendFile(list);

				List<Byte> playlist = getFileInfo(url + fileName);
				s.sendFileName(playlist.size() + 100, fileName);
				s.sendFile(playlist);

			} catch (IOException e) {
				e.printStackTrace();
			}
			s.play(n);
		} else {
			logger.info("设备不在线");
		}
	}

    //---------------------------- property -------------------------------

    @Resource
    private GuideScreenService guideScreenService;

}
